/**
 * @author Gao Jian
 * @email gaoj@njupt.edu.cn
 * @create date 2021-06-03 10:23:40
 * @desc
 */

#define cimg_use_tiff

#include <CImg.h>
#include <cuda_runtime.h>
#include <gdal/gdal.h>
#include <iostream>

using namespace std;
using namespace cimg_library;

void filter_IS(unsigned char *data, unsigned int nw, unsigned int nh,
               unsigned int nd);
void PrintDeviceInfo();

int main(int argc, char **argv) {

  if (argc != 6) {
    printf("INCORRECT parameters, Plaese check your settings!!!\n");
    return -1;
  }

  const unsigned verbose = cimg_option("-v", 1, "verbose.");
  const unsigned device_id = cimg_option("-d", 0, "device ID.");

  int deviceCount;
  cudaGetDeviceCount(&deviceCount);

  if (verbose) {
    PrintDeviceInfo();
    printf("Selected Device : %d.\n", device_id);
  }
  if (device_id >= deviceCount) {
    if (verbose)
      cout << "Incorrect ID " << device_id << ", should less than "
           << deviceCount << "!!!" << endl;
    return -1;
  }
  cudaSetDevice(device_id);

  if (verbose)
    printf("========== IS Filter. ==========\n");

  for (int i = 1; i < argc; i++) {
    printf(" [%d] - %s .\n", i, argv[i]);
  }

  // =========================================================================
  GDALAllRegister();
  GDALDatasetH hDataset[argc - 1];
  GDALRasterBandH hBand[argc - 1];
  for (int i = 0; i < argc - 1; i++) {
    hDataset[i] = GDALOpen(argv[i + 1], GA_Update);
    hBand[i] = GDALGetRasterBand(hDataset[i], 1);
  }

  int nw = GDALGetRasterBandXSize(hBand[0]);
  int nh = GDALGetRasterBandYSize(hBand[0]);

  CImg<unsigned char> data(nw, nh, argc - 1);
  CPLErr error;
  for (int i = 0; i < argc - 1; i++) {
    error =
        GDALRasterIO(hBand[i], GF_Read, 0, 0, nw, nh,
                     data.get_shared_slice(i).data(), nw, nh, GDT_Byte, 0, 0);
  }

  filter_IS(data.data(), nw, nh, argc - 1);

  // =========================================================================

  for (int i = 0; i < argc - 1; i++) {
    error =
        GDALRasterIO(hBand[i], GF_Write, 0, 0, nw, nh,
                     data.get_shared_slice(i).data(), nw, nh, GDT_Byte, 0, 0);
    GDALClose(hDataset[i]);
  }

  // =========================================================================

  if (verbose)
    printf("========================= <<<< Finished. >>>> "
           "=========================\n");

  return 0;
}
